/**
 * Copyright 2014 opencxa.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.cxa.rpc.messages;

import java.util.Map;

import org.cxa.misc.ClassUtils;
import org.cxa.misc.NumberUtils;
import org.cxa.rpc.provider.RpcException;


/**
 * @author Christopher Armenio
 *
 */
public class ResponseRpcMessage extends RpcMessage
{
	public static final String CREATED_FROM_REQUEST = "createdFromRequest";
		
	
	public ResponseRpcMessage(RpcMessage msgIn)
	{
		super(msgIn);
	}
	
	
	/*
	 * for successful responses
	 */
	public ResponseRpcMessage(RequestRpcMessage requestIn, Object returnValueIn)
	{
		super(requestIn.getId(), requestIn.getSource(), requestIn.getCommand(), true, returnValueIn, null);
		this.setMetaData(CREATED_FROM_REQUEST, requestIn);
	}
	
	
	public ResponseRpcMessage(RequestRpcMessage requestIn, RpcException eIn)
	{
		super(requestIn.getId(), requestIn.getSource(), requestIn.getCommand(), false, null, eIn);
		this.setMetaData(CREATED_FROM_REQUEST, requestIn);
	}
	
	
	public Integer getId()
	{
		return this.id;
	}
	
	
	public String getDestination()
	{
		return this.dest;
	}
	
	
	public void setDestination(String destIn)
	{
		this.dest = destIn;
	}
	
	
	public Boolean getWasSuccessful()
	{
		return this.success;
	}
	
	
	public String getCommand()
	{
		return this.cmd;
	}
	
	
	@SuppressWarnings("unchecked")
	public Object getReturnValue(Class<?> expectedTypeIn)
	{
		if( this.retValue == null ) return null;
		else if( expectedTypeIn.isInstance(this.retValue) ) return this.retValue;
		
		// if we made it here, we have a little more work to do before we can return our value
		if( this.retValue instanceof Number )
		{
			if( Number.class.isAssignableFrom(expectedTypeIn) ) return NumberUtils.castToClass_strict((Number)this.retValue, (Class<Number>)expectedTypeIn);
			else if( expectedTypeIn == String.class ) return ((Number)this.retValue).toString();
		}
		else if( (this.retValue instanceof Map) && !Map.class.isAssignableFrom(expectedTypeIn) )
		{
			// expecting a class but have a map...maybe we can coerce...
			return ClassUtils.classFromPojoMap(this.retValue, expectedTypeIn);
		}
		
		// if we made it here, we really can't convert the return value to the proper type...
		return null;
	}
	
	
	public RpcException getException()
	{
		if( this.getWasSuccessful() ) return null;
		return this.error;
	}
	
	
	public RequestRpcMessage extractCreatedFromRequest()
	{
		return (RequestRpcMessage)this.getMetaData_byFieldName(CREATED_FROM_REQUEST);
	}
}
